#include "gd32vf103.h"
#include "gd32vf103c_start.h"
#include "rtthread.h"
#include "ff.h"
#include <string.h>
#include <stdio.h>

#define RX_BUF_SIZE 1024U
uint8_t rxbuffer[RX_BUF_SIZE];
__IO uint16_t rxcount = 0;
__IO FlagStatus g_receive_complete = RESET;
__IO FlagStatus g_transfer_complete = RESET;
uint8_t txbuffer[] = "\n\rUSART DMA receive and transmit example, please input 10 bytes:\n\r";
#define ARRAYNUM(arr_name)     (uint32_t)(sizeof(arr_name) / sizeof(*(arr_name)))

static rt_thread_t donghaomin = RT_NULL;

FATFS fs;

void led_process_thread_entry(void *parameter)
{
    unsigned int count = 0;
    while(1)
    {
        rt_thread_mdelay(500);
        gpio_bit_write(GPIOC, GPIO_PIN_13, (bit_status)(1-gpio_input_bit_get(GPIOC, GPIO_PIN_13)));
//        rt_kprintf("new thread1 led count = %d\n", count);
        rt_thread_mdelay(500);
        count++;
    }
}

void led_process_thread_entry1(void *parameter)
{
    unsigned int count = 0;
    while(1)
    {
        rt_thread_mdelay(500);
        gpio_bit_write(GPIOC, GPIO_PIN_13, (bit_status)(1-gpio_input_bit_get(GPIOC, GPIO_PIN_13)));
//        rt_kprintf("new thread1 led count = %d\n", count);
        rt_thread_mdelay(500);
        count++;
    }
}

void usart0_transmit_arr(uint8_t arr[], uint32_t length) {
    for(uint32_t i=0; i<length; i++) {
        usart_data_transmit(USART1, arr[i]);
        while (usart_flag_get(USART1, USART_FLAG_TBE)== RESET);
    }
}

int main(void)
{
    FIL fil;
    FRESULT fr;     /* FatFs return code */
    UINT br;
    unsigned long long count = 0;

    rcu_periph_clock_enable(RCU_GPIOC);
    gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);

    donghaomin = rt_thread_create("led_thread", led_process_thread_entry,RT_NULL, 512, 2, 10);
    rt_thread_startup(donghaomin);

    dma_parameter_struct dma_init_struct;
    /* enable DMA0 clock */
    rcu_periph_clock_enable(RCU_DMA0);
    /* initialize USART */
    gd_eval_com_init(EVAL_COM1);
    /*configure DMA0 interrupt*/
    eclic_global_interrupt_enable();
    eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL3_PRIO1);
    eclic_irq_enable(DMA0_Channel5_IRQn, 2, 0);

    /* deinitialize DMA channel5 (USART0 rx) */
    dma_deinit(DMA0, DMA_CH5);
    dma_struct_para_init(&dma_init_struct);

    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)rxbuffer;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = 50;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART1);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH5, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_enable(DMA0, DMA_CH5);
    dma_memory_to_memory_disable(DMA0, DMA_CH5);

    /* USART DMA0 enable for reception */
    usart_dma_receive_config(USART1, USART_DENR_ENABLE);
    /* enable DMA0 channel4 transfer complete interrupt */
    dma_interrupt_enable(DMA0, DMA_CH5, DMA_INT_FTF);
    /* enable DMA0 channel4 */
    dma_channel_enable(DMA0, DMA_CH5);

    rt_kprintf("start mount \n");
    fr = f_mount(&fs, "", 1);
    if (fr) rt_kprintf("f_mount error: %d!\n", (int)fr);
    fr = f_open(&fil, "dd.txt", FA_CREATE_ALWAYS|FA_WRITE);
    if (fr) rt_kprintf("open error: %d!\n", (int)fr);
    fr = f_write(&fil,"hello world\n",13,&br);
    if (fr) rt_kprintf("write error: %d!\n", (int)fr);
    fr = f_sync(&fil);
    if (fr) rt_kprintf("sync error: %d!\n", (int)fr);

    while(1){
        /* waiting for the transfer to complete*/
        while(RESET == g_transfer_complete);
        g_transfer_complete = RESET;
        rt_kprintf("%s", rxbuffer);
        fr = f_write(&fil,rxbuffer,50,&br);
        if (fr) rt_kprintf("write error: %d!\n", (int)fr);
        fr = f_sync(&fil);
        if (fr) rt_kprintf("sync error: %d!\n", (int)fr);
    }
}

void USART1_IRQHandler(void) {
    if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE)){
        /* receive data */
        rxbuffer[rxcount++] = usart_data_receive(USART1);
            if ((rxbuffer[rxcount - 2] == 0x0D)&&(rxbuffer[rxcount -1] == 0x0A)) {
            usart_interrupt_disable(USART1, USART_INT_RBNE);
            g_receive_complete = SET;
        }
    }
}

void DMA0_Channel5_IRQHandler(void)
{
    if(dma_interrupt_flag_get(DMA0, DMA_CH5, DMA_INT_FLAG_FTF)){
        dma_interrupt_flag_clear(DMA0, DMA_CH5, DMA_INT_FLAG_G);
        g_transfer_complete = SET;
    }
}

/* retarget the C library printf function to the USART */
int _put_char(int ch)
{
    usart_data_transmit(USART1, (uint8_t)ch );
    while ( usart_flag_get(USART1, USART_FLAG_TBE)== RESET){
    }

    return ch;
}
size_t rtt_write(int fd, const void* ptr, size_t len)
{
    const uint8_t * writebuf = (const uint8_t *)ptr;
    for (size_t i = 0; i < len; i ++) {
        if (writebuf[i] == '\n') {
            usart_write(USART0,'\r');
        }
        usart_write(USART0,writebuf[i]);
    }
    return len;
}
void rt_hw_console_output(const char *str)
{
    rt_size_t size = 0;

    size = rt_strlen(str);
    rtt_write(1, str, size);
}

#if !FF_FS_NORTC && !FF_FS_READONLY
DWORD get_fattime (void)
{
    return    ((DWORD)(2015 - 1980) << 25)  /* Year 2015 */
                    | ((DWORD)1 << 21)              /* Month 1 */
                    | ((DWORD)1 << 16)              /* Mday 1 */
                    | ((DWORD)0 << 11)              /* Hour 0 */
                    | ((DWORD)0 << 5)                 /* Min 0 */
                    | ((DWORD)0 >> 1);              /* Sec 0 */

}
#endif
